home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / hplip / fax / soapfax.py < prev    next >
Text File  |  2009-10-09  |  29KB  |  720 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20. #
  21.  
  22. from __future__ import division
  23.  
  24. # Std Lib
  25. import sys
  26. import os
  27. import time
  28. import cStringIO
  29. import urllib # TODO: Replace with urllib2 (urllib is deprecated in Python 3.0)
  30. import re
  31.  
  32. # Local
  33. from base.g import *
  34. from base.codes import *
  35. from base import device, utils, codes, dime
  36. from fax import *
  37.  
  38. #import xml.parsers.expat as expat
  39.  
  40.  
  41. # **************************************************************************** #
  42.  
  43. http_result_pat = re.compile("""HTTP/\d.\d\s(\d+)""", re.I)
  44.  
  45.  
  46. TIME_FORMAT_AM_PM = 1
  47. TIME_FORMAT_24HR = 2
  48.  
  49. DATE_FORMAT_MM_DD_YYYY = 1
  50. DATE_FORMAT_DD_MM_YYYY = 2
  51. DATE_FORMAT_YYYY_MM_DD = 3
  52.  
  53. AM = 1
  54. PM = 0
  55.  
  56. HTTP_OK = 200
  57. HTTP_ERROR = 500
  58.  
  59. PIXELS_PER_LINE = 2528
  60.  
  61.  
  62. # **************************************************************************** #
  63. class SOAPFaxDevice(FaxDevice):
  64.  
  65.     def __init__(self, device_uri=None, printer_name=None,
  66.                  callback=None,
  67.                  fax_type=FAX_TYPE_NONE,
  68.                  disable_dbus=False):
  69.  
  70.         FaxDevice.__init__(self, device_uri,
  71.                            printer_name,
  72.                            callback, fax_type,
  73.                            disable_dbus)
  74.  
  75.         self.send_fax_thread = None
  76.         self.upload_log_thread = None
  77.  
  78.         if self.bus == 'net':
  79.             self.http_host = self.host
  80.         else:
  81.             self.http_host = 'localhost'
  82.  
  83.  
  84.     def post(self, url, post):
  85.         s = []
  86.         for k, v in post.items():
  87.             s.append("%s=%s" % (k, urllib.quote(str(v))))
  88.  
  89.         s = '&'.join(s)
  90.  
  91.         log.debug(s)
  92.  
  93.         data = """POST %s HTTP/1.1
  94. Connection: Keep-alive
  95. User-agent: hplip/2.0
  96. Host: %s
  97. Content-length: %d
  98. Cache-control: No-cache
  99.  
  100. %s""" % (url, self.http_host, len(s), s)
  101.  
  102.         log.log_data(data)
  103.         self.writeEWS(data)
  104.         ret = cStringIO.StringIO()
  105.  
  106.         while self.readEWS(4096, ret, timeout=5):
  107.             pass
  108.  
  109.         ret = ret.getvalue()
  110.  
  111.         log.log_data(ret)
  112.  
  113.         self.closeEWS()
  114.  
  115.         match = http_result_pat.match(ret)
  116.  
  117.         try:
  118.             code = int(match.group(1))
  119.         except (ValueError, TypeError):
  120.             code = HTTP_ERROR
  121.  
  122.         return code == HTTP_OK
  123.  
  124.  
  125.     def setPhoneNum(self, num):
  126.         return self.post("/hp/device/set_config.html", {"FaxNumber": str(num)})
  127.  
  128.  
  129.     def getPhoneNum(self):
  130.         stream = cStringIO.StringIO()
  131.         self.getEWSUrl("/hp/device/settings_fax_setup_wizard.xml", stream)
  132.         fax_setup = utils.XMLToDictParser().parseXML(stream.getvalue())
  133.         return fax_setup['faxsetupwizard-faxvoicenumber-faxnumber']
  134.  
  135.     phone_num = property(getPhoneNum, setPhoneNum)
  136.  
  137.  
  138.     def setStationName(self, name):
  139.         return self.post("/hp/device/set_config.html", {"FaxCompanyName": str(name)})
  140.  
  141.  
  142.     def getStationName(self):
  143.         stream = cStringIO.StringIO()
  144.         self.getEWSUrl("/hp/device/settings_fax_setup_wizard.xml", stream)
  145.         fax_setup = utils.XMLToDictParser().parseXML(stream.getvalue())
  146.         return fax_setup['faxsetupwizard-userinformation-faxcompanyname']
  147.  
  148.     station_name = property(getStationName, setStationName)
  149.  
  150.  
  151.     def setDateAndTime(self):
  152.         stream = cStringIO.StringIO()
  153.         self.getEWSUrl("/hp/device/settings_fax_setup_wizard.xml", stream)
  154.         fax_setup = utils.XMLToDictParser().parseXML(stream.getvalue())
  155.         timeformat = fax_setup['faxsetupwizard-time-timeformat']
  156.  
  157.         try:
  158.             timeformat = int(timeformat)
  159.         except (ValueError, TypeError):
  160.             timeformat = TIME_FORMAT_AM_PM
  161.  
  162.         log.debug("timeformat: %d" % timeformat)
  163.  
  164.         dateformat = fax_setup['faxsetupwizard-date-dateformat']
  165.  
  166.         try:
  167.             dateformat = int(dateformat)
  168.         except (ValueError, TypeError):
  169.             dateformat = DATE_FORMAT_DD_MM_YYYY
  170.  
  171.         log.debug("dateformat: %d" % dateformat)
  172.  
  173.         t = time.localtime()
  174.         hr = t[3]
  175.  
  176.         am_pm = PM
  177.         if t[3] < 12:
  178.             am_pm = AM
  179.  
  180.         if timeformat == TIME_FORMAT_AM_PM and hr > 12:
  181.             hr -= 12
  182.  
  183.         post = {"DateFormat" : dateformat,
  184.                 "Year" : t[0],
  185.                 "Month" : t[1],
  186.                 "Day" : t[2],
  187.                 "TimeFormat" : timeformat,
  188.                 "Hour" : hr,
  189.                 "Minute" : t[4]}
  190.  
  191.         if timeformat == TIME_FORMAT_AM_PM:
  192.             post['AM'] = am_pm
  193.  
  194.         return self.post("/hp/device/set_config.html", post)
  195.  
  196.  
  197.     def sendFaxes(self, phone_num_list, fax_file_list, cover_message='', cover_re='',
  198.                   cover_func=None, preserve_formatting=False, printer_name='',
  199.                   update_queue=None, event_queue=None):
  200.  
  201.         if not self.isSendFaxActive():
  202.  
  203.             self.send_fax_thread = SOAPFaxSendThread(self, self.service, phone_num_list, fax_file_list,
  204.                                                      cover_message, cover_re, cover_func,
  205.                                                      preserve_formatting,
  206.                                                      printer_name, update_queue,
  207.                                                      event_queue)
  208.  
  209.             self.send_fax_thread.start()
  210.             return True
  211.         else:
  212.             return False
  213.  
  214.  
  215. # **************************************************************************** #
  216. class SOAPFaxSendThread(FaxSendThread):
  217.     def __init__(self, dev, service, phone_num_list, fax_file_list,
  218.                  cover_message='', cover_re='', cover_func=None, preserve_formatting=False,
  219.                  printer_name='', update_queue=None, event_queue=None):
  220.  
  221.         FaxSendThread.__init__(self, dev, service, phone_num_list, fax_file_list,
  222.              cover_message, cover_re, cover_func, preserve_formatting,
  223.              printer_name, update_queue, event_queue)
  224.  
  225.         self.job_id = utils.gen_random_uuid()
  226.         log.debug("JobId: %s" % self.job_id)
  227.  
  228.         if dev.bus == 'net':
  229.             self.http_host = "%s:8295" % self.dev.host
  230.         else:
  231.             self.http_host = 'localhost:8295'
  232.  
  233.         #self.http_host = 'localhost'
  234.  
  235.  
  236.     def run(self):
  237.         #results = {} # {'file' : error_code,...}
  238.  
  239.         STATE_DONE = 0
  240.         STATE_ABORTED = 10
  241.         STATE_SUCCESS = 20
  242.         STATE_BUSY = 25
  243.         STATE_READ_SENDER_INFO = 30
  244.         STATE_PRERENDER = 40
  245.         STATE_COUNT_PAGES = 50
  246.         STATE_NEXT_RECIPIENT = 60
  247.         STATE_COVER_PAGE = 70
  248.         STATE_SINGLE_FILE = 80
  249.         STATE_MERGE_FILES = 90
  250.         STATE_SINGLE_FILE = 100
  251.         STATE_SEND_FAX = 110
  252.         STATE_CLEANUP = 120
  253.         STATE_ERROR = 130
  254.  
  255.         next_recipient = self.next_recipient_gen()
  256.  
  257.         state = STATE_READ_SENDER_INFO
  258.         self.rendered_file_list = []
  259.  
  260.         while state != STATE_DONE: # --------------------------------- Fax state machine
  261.             if self.check_for_cancel():
  262.                 state = STATE_ABORTED
  263.  
  264.             log.debug("STATE=(%d, 0, 0)" % state)
  265.  
  266.             if state == STATE_ABORTED: # --------------------------------- Aborted (10, 0, 0)
  267.                 log.error("Aborted by user.")
  268.                 self.write_queue((STATUS_IDLE, 0, ''))
  269.                 state = STATE_CLEANUP
  270.  
  271.  
  272.             elif state == STATE_SUCCESS: # --------------------------------- Success (20, 0, 0)
  273.                 log.debug("Success.")
  274.                 self.write_queue((STATUS_COMPLETED, 0, ''))
  275.                 state = STATE_CLEANUP
  276.  
  277.  
  278.             elif state == STATE_ERROR: # --------------------------------- Error (130, 0, 0)
  279.                 log.error("Error, aborting.")
  280.                 self.write_queue((STATUS_ERROR, 0, ''))
  281.                 state = STATE_CLEANUP
  282.  
  283.  
  284.             elif state == STATE_BUSY: # --------------------------------- Busy (25, 0, 0)
  285.                 log.error("Device busy, aborting.")
  286.                 self.write_queue((STATUS_BUSY, 0, ''))
  287.                 state = STATE_CLEANUP
  288.  
  289.  
  290.             elif state == STATE_READ_SENDER_INFO: # --------------------------------- Get sender info (30, 0, 0)
  291.                 log.debug("%s State: Get sender info" % ("*"*20))
  292.                 state = STATE_PRERENDER
  293.                 try:
  294.                     try:
  295.                         self.dev.open()
  296.                     except Error, e:
  297.                         log.error("Unable to open device (%s)." % e.msg)
  298.                         state = STATE_ERROR
  299.                     else:
  300.                         try:
  301.                             self.sender_name = self.dev.station_name
  302.                             log.debug("Sender name=%s" % self.sender_name)
  303.                             self.sender_fax = self.dev.phone_num
  304.                             log.debug("Sender fax=%s" % self.sender_fax)
  305.                         except Error:
  306.                             log.error("HTTP GET failed!")
  307.                             state = STATE_ERROR
  308.  
  309.                 finally:
  310.                     self.dev.close()
  311.  
  312.  
  313.             elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G4 files (40, 0, 0)
  314.                 log.debug("%s State: Pre-render non-G4 files" % ("*"*20))
  315.                 state = self.pre_render(STATE_COUNT_PAGES)
  316.  
  317.             elif state == STATE_COUNT_PAGES: # --------------------------------- Get total page count (50, 0, 0)
  318.                 log.debug("%s State: Get total page count" % ("*"*20))
  319.                 state = self.count_pages(STATE_NEXT_RECIPIENT)
  320.  
  321.             elif state == STATE_NEXT_RECIPIENT: # --------------------------------- Loop for multiple recipients (60, 0, 0)
  322.                 log.debug("%s State: Next recipient" % ("*"*20))
  323.                 state = STATE_COVER_PAGE
  324.  
  325.                 try:
  326.                     recipient = next_recipient.next()
  327.                     log.debug("Processing for recipient %s" % recipient['name'])
  328.                     self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
  329.                 except StopIteration:
  330.                     state = STATE_SUCCESS
  331.                     log.debug("Last recipient.")
  332.                     continue
  333.  
  334.                 recipient_file_list = self.rendered_file_list[:]
  335.  
  336.  
  337.             elif state == STATE_COVER_PAGE: # --------------------------------- Create cover page (70, 0, 0)
  338.                 log.debug("%s State: Render cover page" % ("*"*20))
  339.                 state = self.cover_page(recipient)
  340.  
  341.  
  342.             elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
  343.                 log.debug("%s State: Handle single file" % ("*"*20))
  344.                 state = self.single_file(STATE_SEND_FAX)
  345.  
  346.             elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G4 files (90, 0, 0)
  347.                 log.debug("%s State: Merge multiple files" % ("*"*20))
  348.                 state = self.merge_files(STATE_SEND_FAX)
  349.  
  350.             elif state == STATE_SEND_FAX: # --------------------------------- Send fax state machine (110, 0, 0)
  351.                 log.debug("%s State: Send fax" % ("*"*20))
  352.                 state = STATE_NEXT_RECIPIENT
  353.  
  354.                 FAX_SEND_STATE_DONE = 0
  355.                 FAX_SEND_STATE_ABORT = 10
  356.                 FAX_SEND_STATE_ERROR = 20
  357.                 FAX_SEND_STATE_BUSY = 25
  358.                 FAX_SEND_STATE_SUCCESS = 30
  359.                 FAX_SEND_STATE_DEVICE_OPEN = 40
  360.                 FAX_SEND_STATE_BEGINJOB = 50
  361.                 FAX_SEND_STATE_DOWNLOADPAGES = 60
  362.                 FAX_SEND_STATE_ENDJOB = 70
  363.                 FAX_SEND_STATE_CANCELJOB = 80
  364.                 FAX_SEND_STATE_CLOSE_SESSION = 170
  365.  
  366.                 monitor_state = False
  367.                 fax_send_state = FAX_SEND_STATE_DEVICE_OPEN
  368.  
  369.                 while fax_send_state != FAX_SEND_STATE_DONE:
  370.  
  371.                     if self.check_for_cancel():
  372.                         log.error("Fax send aborted.")
  373.                         fax_send_state = FAX_SEND_STATE_ABORT
  374.  
  375.                     if monitor_state:
  376.                         fax_state = self.getFaxDownloadState()
  377.                         if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
  378.                             log.error("D/L error state=%d" % fax_state)
  379.                             fax_send_state = FAX_SEND_STATE_ERROR
  380.                             state = STATE_ERROR
  381.  
  382.                     log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))
  383.  
  384.                     if fax_send_state == FAX_SEND_STATE_ABORT: # -------------- Abort (110, 10, 0)
  385.                         monitor_state = False
  386.                         fax_send_state = FAX_SEND_STATE_CANCELJOB
  387.                         state = STATE_ABORTED
  388.  
  389.                     elif fax_send_state == FAX_SEND_STATE_ERROR: # -------------- Error (110, 20, 0)
  390.                         log.error("Fax send error.")
  391.                         monitor_state = False
  392.                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  393.                         state = STATE_ERROR
  394.  
  395.                     elif fax_send_state == FAX_SEND_STATE_BUSY: # -------------- Busy (110, 25, 0)
  396.                         log.error("Fax device busy.")
  397.                         monitor_state = False
  398.                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  399.                         state = STATE_BUSY
  400.  
  401.                     elif fax_send_state == FAX_SEND_STATE_SUCCESS: # -------------- Success (110, 30, 0)
  402.                         log.debug("Fax send success.")
  403.                         monitor_state = False
  404.                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  405.                         state = STATE_NEXT_RECIPIENT
  406.  
  407.                     elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # -------------- Device open (110, 40, 0)
  408.                         log.debug("%s State: Open device" % ("*"*20))
  409.                         fax_send_state = FAX_SEND_STATE_BEGINJOB
  410.                         try:
  411.                             self.dev.open()
  412.                         except Error, e:
  413.                             log.error("Unable to open device (%s)." % e.msg)
  414.                             fax_send_state = FAX_SEND_STATE_ERROR
  415.                         else:
  416.                             if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
  417.                                 fax_send_state = FAX_SEND_STATE_ERROR
  418.  
  419.                     elif fax_send_state == FAX_SEND_STATE_BEGINJOB: # -------------- BeginJob (110, 50, 0)
  420.                         log.debug("%s State: BeginJob" % ("*"*20))
  421.  
  422.                         try:
  423.                             ff = file(self.f, 'r')
  424.                         except IOError:
  425.                             log.error("Unable to read fax file.")
  426.                             fax_send_state = FAX_SEND_STATE_ERROR
  427.                             continue
  428.  
  429.                         try:
  430.                             header = ff.read(FILE_HEADER_SIZE)
  431.                         except IOError:
  432.                             log.error("Unable to read fax file.")
  433.                             fax_send_state = FAX_SEND_STATE_ERROR
  434.                             continue
  435.  
  436.                         magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
  437.                             resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)
  438.  
  439.                         if magic != 'hplip_g3':
  440.                             log.error("Invalid file header. Bad magic.")
  441.                             fax_send_state = FAX_SEND_STATE_ERROR
  442.                         else:
  443.                             log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
  444.                                       (magic, version, total_pages, hort_dpi, vert_dpi, page_size,
  445.                                        resolution, encoding))
  446.  
  447.                         job_id = self.job_id
  448.                         delay = 0
  449.                         faxnum = recipient['fax'].encode('ascii')
  450.                         speeddial = 0
  451.  
  452.                         if resolution == RESOLUTION_STD:
  453.                             res = "STANDARD"
  454.                         elif resolution == RESOLUTION_FINE:
  455.                             res = "FINE"
  456.                         elif resolution == RESOLUTION_300DPI:
  457.                             res = "SUPERFINE"
  458.  
  459.                         soap = utils.cat(
  460. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><Fax:BeginJob xmlns:Fax="urn:Fax"><ticket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Fax:Ticket"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$job_id</jobId><resolution xsi:type="Fax:Resolution">$res</resolution><delay xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$delay</delay><phoneNumber xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$faxnum</phoneNumber><speedDial xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$speeddial</speedDial></ticket></Fax:BeginJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  461.  
  462.                         data = self.format_http(soap)
  463.                         log.log_data(data)
  464.  
  465.                         if log.is_debug():
  466.                             file('beginjob.log', 'w').write(data)
  467.  
  468.                         self.dev.openSoapFax()
  469.                         self.dev.writeSoapFax(data)
  470.                         ret = cStringIO.StringIO()
  471.  
  472.                         while self.dev.readSoapFax(8192, ret, timeout=5):
  473.                             pass
  474.  
  475.                         ret = ret.getvalue()
  476.  
  477.                         if log.is_debug():
  478.                             file('beginjob_ret.log', 'w').write(ret)
  479.  
  480.                         log.log_data(ret)
  481.                         self.dev.closeSoapFax()
  482.  
  483.                         if self.get_error_code(ret) == HTTP_OK:
  484.                             fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
  485.                         else:
  486.                             fax_send_state = FAX_SEND_STATE_ERROR
  487.  
  488.  
  489.                     elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES: # -------------- DownloadPages (110, 60, 0)
  490.                         log.debug("%s State: DownloadPages" % ("*"*20))
  491.                         page = StringIO()
  492.                         for p in range(total_pages):
  493.  
  494.                             if self.check_for_cancel():
  495.                                 fax_send_state = FAX_SEND_STATE_ABORT
  496.  
  497.                             if fax_send_state == FAX_SEND_STATE_ABORT:
  498.                                 break
  499.  
  500.                             try:
  501.                                 header = ff.read(PAGE_HEADER_SIZE)
  502.                             except IOError:
  503.                                 log.error("Unable to read fax file.")
  504.                                 fax_send_state = FAX_SEND_STATE_ERROR
  505.                                 continue
  506.  
  507.                             page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
  508.                                 self.decode_page_header(header)
  509.  
  510.                             log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
  511.                                       (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))
  512.  
  513.                             if ppr != PIXELS_PER_LINE:
  514.                                 log.error("Pixels per line (width) must be %d!" % PIXELS_PER_LINE)
  515.  
  516.                             page.write(ff.read(bytes_to_read))
  517.                             thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
  518.                             page.seek(0)
  519.  
  520.                             try:
  521.                                 data = page.read(bytes_to_read)
  522.                             except IOError:
  523.                                 log.error("Unable to read fax file.")
  524.                                 fax_send_state = FAX_SEND_STATE_ERROR
  525.                                 break
  526.  
  527.                             if data == '':
  528.                                 log.error("No data!")
  529.                                 fax_send_state = FAX_SEND_STATE_ERROR
  530.                                 break
  531.  
  532.                             height = rpp
  533.                             job_id = self.job_id
  534.  
  535.                             soap = utils.cat(
  536. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:DownloadPage xmlns:Fax="urn:Fax"><height xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:positiveInteger">$height</height></Fax:DownloadPage></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  537.  
  538.                             m = dime.Message()
  539.                             m.add_record(dime.Record("cid:id0", "http://schemas.xmlsoap.org/soap/envelope/",
  540.                                 dime.TYPE_T_URI, soap))
  541.  
  542.                             m.add_record(dime.Record("", "image/g4fax", dime.TYPE_T_MIME, data))
  543.  
  544.                             output = cStringIO.StringIO()
  545.                             m.generate(output)
  546.                             data = self.format_http(output.getvalue(), content_type="application/dime")
  547.                             log.log_data(data)
  548.                             if log.is_debug():
  549.                                 file('downloadpages%d.log' % p, 'w').write(data)
  550.  
  551.                             try:
  552.                                 self.dev.writeSoapFax(data)
  553.                             except Error:
  554.                                 fax_send_state = FAX_SEND_STATE_ERROR
  555.  
  556.                             ret = cStringIO.StringIO()
  557.  
  558.                             try:
  559.                                 while self.dev.readSoapFax(8192, ret, timeout=5):
  560.                                     pass
  561.                             except Error:
  562.                                 fax_send_state = FAX_SEND_STATE_ERROR
  563.  
  564.                             ret = ret.getvalue()
  565.  
  566.                             if log.is_debug():
  567.                                 file('downloadpages%d_ret.log' % p, 'w').write(ret)
  568.  
  569.                             log.log_data(ret)
  570.                             self.dev.closeSoapFax()
  571.  
  572.                             if self.get_error_code(ret) != HTTP_OK:
  573.                                 fax_send_state = FAX_SEND_STATE_ERROR
  574.                                 break
  575.  
  576.                             page.truncate(0)
  577.                             page.seek(0)
  578.  
  579.                         else:
  580.                             fax_send_state = FAX_SEND_STATE_ENDJOB
  581.  
  582.  
  583.                     elif fax_send_state == FAX_SEND_STATE_ENDJOB: # -------------- EndJob (110, 70, 0)
  584.                         log.debug("%s State: EndJob" % ("*"*20))
  585.  
  586.                         job_id = self.job_id
  587.  
  588.                         soap = utils.cat(
  589. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:EndJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:EndJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  590.  
  591.                         data = self.format_http(soap)
  592.  
  593.                         log.log_data(data)
  594.  
  595.                         if log.is_debug():
  596.                             file('endjob.log', 'w').write(data)
  597.  
  598.                         self.dev.writeSoapFax(data)
  599.                         ret = cStringIO.StringIO()
  600.  
  601.                         while self.dev.readSoapFax(8192, ret, timeout=5):
  602.                             pass
  603.  
  604.                         ret = ret.getvalue()
  605.  
  606.                         if log.is_debug():
  607.                             file('endjob_ret.log', 'w').write(ret)
  608.  
  609.                         log.log_data(ret)
  610.                         self.dev.closeSoapFax()
  611.  
  612.                         if self.get_error_code(ret) == HTTP_OK:
  613.                             fax_send_state = FAX_SEND_STATE_SUCCESS
  614.                         else:
  615.                             fax_send_state = FAX_SEND_STATE_ERROR
  616.  
  617.                     elif fax_send_state == FAX_SEND_STATE_CANCELJOB: # -------------- CancelJob (110, 80, 0)
  618.                         log.debug("%s State: CancelJob" % ("*"*20))
  619.  
  620.                         job_id = self.job_id
  621.  
  622.                         soap = utils.cat(
  623. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:CancelJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:CancelJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  624.  
  625.                         data = self.format_http(soap)
  626.  
  627.                         log.log_data(data)
  628.  
  629.                         if log.is_debug():
  630.                             file('canceljob.log', 'w').write(data)
  631.  
  632.                         self.dev.writeSoapFax(data)
  633.                         ret = cStringIO.StringIO()
  634.  
  635.                         while self.dev.readSoapFax(8192, ret, timeout=5):
  636.                             pass
  637.  
  638.                         ret = ret.getvalue()
  639.  
  640.                         if log.is_debug():
  641.                             file('canceljob_ret.log', 'w').write(ret)
  642.  
  643.                         log.log_data(ret)
  644.                         self.dev.closeSoapFax()
  645.  
  646.                         if self.get_error_code(ret) == HTTP_OK:
  647.                             fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  648.                         else:
  649.                             fax_send_state = FAX_SEND_STATE_ERROR
  650.  
  651.  
  652.                     elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
  653.                         log.debug("%s State: Close session" % ("*"*20))
  654.                         log.debug("Closing session...")
  655.  
  656.                         try:
  657.                             mm.close()
  658.                         except NameError:
  659.                             pass
  660.  
  661.                         try:
  662.                             ff.close()
  663.                         except NameError:
  664.                             pass
  665.  
  666.                         time.sleep(1)
  667.  
  668.                         self.dev.closeSoapFax()
  669.                         self.dev.close()
  670.  
  671.                         fax_send_state = FAX_SEND_STATE_DONE # Exit inner state machine
  672.  
  673.  
  674.             elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
  675.                 log.debug("%s State: Cleanup" % ("*"*20))
  676.  
  677.                 if self.remove_temp_file:
  678.                     log.debug("Removing merged file: %s" % self.f)
  679.                     try:
  680.                         os.remove(self.f)
  681.                         log.debug("Removed")
  682.                     except OSError:
  683.                         log.debug("Not found")
  684.  
  685.                 state = STATE_DONE # Exit outer state machine
  686.  
  687.  
  688.     def get_error_code(self, ret):
  689.         if not ret: return HTTP_ERROR
  690.  
  691.         match = http_result_pat.match(ret)
  692.  
  693.         if match is None: return HTTP_OK
  694.         try:
  695.             code = int(match.group(1))
  696.         except (ValueError, TypeError):
  697.             code = HTTP_ERROR
  698.  
  699.         return code
  700.  
  701.  
  702.     def format_http(self, soap, content_type="text/xml; charset=utf-8"):
  703.         host = self.http_host
  704.         soap_len = len(soap)
  705.  
  706.         return utils.cat(
  707. """POST / HTTP/1.1\r
  708. Host: $host\r
  709. User-Agent: hplip/2.0\r
  710. Content-Type: $content_type\r
  711. Content-Length: $soap_len\r
  712. Connection: close\r
  713. SOAPAction: ""\r
  714. \r
  715. $soap""")
  716.  
  717.  
  718.  
  719.  
  720.